package hu.dobrosi.dinkycam.j2me.screens;

import hu.dobrosi.dinkycam.j2me.DinkycamApp;
import hu.dobrosi.dinkycam.j2me.Labels;
import hu.dobrosi.util.StringUtil;

import java.io.IOException;

import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.VideoControl;

public class CaptureCanvas extends DinkycamCanvas implements CommandListener {
	protected static final String DIMENSION = "width=640&height=480";
	private Player player = null;
	private Command snapshotCommand = null;
	private VideoControl videoControl = null;
	private Command cmdSettings;
	private boolean gpsTimerStarted;
	private boolean camTimerStarted;
	private Thread gpsThread;
	private Thread cameraThread;

	public CaptureCanvas(final DinkycamApp app) {
		super(app);
		setTitle(Labels.TITLE_RECORDING.toString());
		addCommand(cmdSettings = new Command(Labels.SETTINGS.toString(),
				Command.ITEM, 300));
		snapshotCommand = new Command(Labels.SENDING.toString(), Command.OK, 1);
		addCommand(snapshotCommand);
		setCommandListener(this);
	}

	public void paint(Graphics g) {
		super.paint(g);
	}

	public void commandAction(Command c, Displayable d) {
		super.commandAction(c, d);
		if (c == snapshotCommand) {
			try {
				snapshot(true);
			} catch (IOException e) {
				StringUtil.logger.clear();
				StringUtil.logger.print(e);
			}
		} else if (c == cmdSettings) {
			app.showSettings();
		}
	}

	public void keyPressed(int keyCode) {
		if (getGameAction(keyCode) == FIRE) {
			try {
				snapshot(true);
			} catch (IOException e) {
				StringUtil.logger.clear();
				StringUtil.logger.print(e);
			}
		}
	}

	public synchronized void startPlayer() {
		StringUtil.logger.println("Start player.");
		String playerType;
		try {
			if (DinkycamApp.isEmulator()) {
				playerType = "capture://video";
			} else {
				playerType = "capture://image";
			}

			player = Manager.createPlayer(playerType);
			player.realize();

			videoControl = (VideoControl) player.getControl("VideoControl");
			if (videoControl == null) {
				discardPlayer();
				app.showError("Cannot get the video control.\n"
						+ "Capture may not be supported.");
				player = null;
			} else {
				videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO,
						this);
				int canvasWidth = getWidth();
				int canvasHeight = getHeight();
				videoControl.setDisplayLocation(0, 0);
				videoControl.setDisplaySize(canvasWidth, canvasHeight);
				player.start();
				videoControl.setVisible(true);
			}
		} catch (IOException e) {
			app.showError(this, "startImage", e);
			discardPlayer();
		} catch (MediaException e) {
			app.showError(this, "startImage", e);

		} catch (SecurityException e) {
			app.showError(this, "startImage", e);
		}
	}

	public synchronized void stopPlayer() {
		discardPlayer();
	}

	public void discardPlayer() {
		if (player != null) {
			player.deallocate();
			player.close();
			player = null;
		}
		videoControl = null;
	}

	public void startCamTimer() {
		cameraThread = new Thread() {
			public void run() {
				camTimerStarted = true;
				while (camTimerStarted) {
					try {
						snapshot(true);
					} catch (Exception e) {
						app.showError(this, "run", e);
					}
					try {
						Thread.sleep(Integer.parseInt(app.getSettingsForm()
								.getCamSleepTextField().getString()) * 1000);
					} catch (NumberFormatException e) {
						StringUtil.logger.clear();
						StringUtil.logger.print(e);
					} catch (InterruptedException e) {
						StringUtil.logger.clear();
						StringUtil.logger.print(e);
					}
				}
			}
		};
		cameraThread.start();
	}

	public void startGpsTimer() {
		gpsThread = new Thread() {
			public void run() {
				gpsTimerStarted = true;
				while (gpsTimerStarted) {
					boolean sleep;
					try {
						sleep = !snapshot(false);
					} catch (Exception e) {
						sleep = true;
						StringUtil.logger.clear();
						StringUtil.logger.println("" + e.getClass().getName());
					}
					try {
						Thread.sleep(getGpsSleepTime(sleep));
					} catch (InterruptedException e) {
						StringUtil.logger.clear();
						StringUtil.logger.println("" + e.getClass().getName());
					}
				}
			}
		};
		gpsThread.start();
	}

	private boolean snapshot(final boolean image) throws IOException {
		try {
			ChoiceGroup encodingsChoiceGroup = app.getSettingsForm()
					.getEncodingsChoiceGroup();
			final byte[] jpgImage = videoControl != null && image ? videoControl
					.getSnapshot("encoding=jpeg&"
							+ encodingsChoiceGroup
									.getString(encodingsChoiceGroup
											.getSelectedIndex())) : null;

			return app.capture(jpgImage);
			// discardPlayer();
		} catch (MediaException e) {
			app.showError(this, "run", e);
		} catch (SecurityException e) {
			app.showError(this, "run", e);
		}
		return false;
	}

	public void cancel() {
		StringUtil.logger.println("Cancel timers.");
		stopPlayer();
		if (camTimerStarted) {
			cameraThread.interrupt();
		}
		if (gpsTimerStarted) {
			gpsThread.interrupt();
		}
		gpsTimerStarted = false;
		camTimerStarted = false;
	}

	public Player getPlayer() {
		return player;
	}

	public void setPlayer(Player player) {
		this.player = player;
	}

	private int getGpsSleepTime(boolean sleep) {
		if (sleep) {
			return app.getAdvancedSettingsForm()
					.getGpsStandbySamplingTimeTextField().getValue() * 1000;
		} else {
			return app.getAdvancedSettingsForm()
					.getGpsMovingSleepTimeTextField().getValue() * 1000;
		}
	}
}